home *** CD-ROM | disk | FTP | other *** search
/ Ian & Stuart's Australian Mac 1993 September / September 93.iso / Archives / Fun, Tricks & Hacks / Windows / MSWindows.c < prev    next >
C/C++ Source or Header  |  1992-06-14  |  34KB  |  1,289 lines

  1. #include "MSWindows.h"
  2.  
  3. /* Globals */
  4. Boolean            gDone = false;
  5.  
  6. RGBColor        gBlack,gWhite,gGray,gLtGray,gDkGray,gBlue;
  7. MSWindowPtr        gPMWindow;
  8. MSWindowPtr        gMineWindow;
  9. MSWindowPtr        gAlertWindow;
  10. GWorldPtr        gGWorld = nil;        /* Offscreen GWorld */
  11.  
  12. short            gSound = true;            /* use sound blaster */
  13. short            gOptions[] = { 1,0,1 };    /* Options menu items (base 0) */
  14. MSChildPtr        gChild[iMaxChild];
  15.  
  16. RgnHandle        gUpRgn,gRightRgn,gURightRgn,gDRightRgn,gArrowRgn;
  17. RgnHandle        gcUpRgn,gcRightRgn,gcURightRgn,gcDRightRgn,gcArrowRgn;
  18. RgnHandle        gClipRgn,gViewRgn,gDrawRgn,gFrameRgn,gParentFrameRgn;
  19.  
  20. PicHandle        gPicts[kMaxPict];
  21. Str31            gPictText[kMaxPict];
  22.  
  23. extern unsigned     long gStartTime;
  24. extern short         gGameType;
  25. extern Boolean        gMarks;
  26. extern MenuHandle    gMenus[menuCount];
  27.  
  28. /* gMac is used to hold the result of a SysEnvirons call. This makes
  29.    it convenient for any routine to check the environment. */
  30. extern SysEnvRec    gMac;            /* set up by Initialize */
  31. extern short        gClicks;        /* Click counter, = 1 single click    */
  32.                                     /*                = 2 double click    */
  33.                                     /*    etc.                            */
  34. #pragma segment TheApp
  35.  
  36. void HideIcon(MSIconPtr icon)
  37. {
  38.     MSChildPtr MSGroup;
  39.     
  40.     MSGroup = icon->group;
  41.     SetPort((WindowPtr)MSGroup->window);
  42.     SetOrigin( -MSGroup->origin.h, -MSGroup->origin.v);
  43.     EraseRect(&icon->iconBox);
  44.     InvalRect(&icon->iconBox);
  45.     OffsetRect(&icon->iconBox,kOffscreenOffset,0);
  46.     EraseRect(&icon->textBox);
  47.     InvalRect(&icon->textBox);
  48.     OffsetRect(&icon->textBox,kOffscreenOffset,0);
  49.     SetOrigin(0,0);
  50. }
  51.  
  52. void ShowIcon(MSIconPtr icon)
  53. {
  54.     MSChildPtr MSGroup;
  55.     
  56.     MSGroup = icon->group;
  57.     SetPort((WindowPtr)MSGroup->window);
  58.     SetOrigin( -MSGroup->origin.h, -MSGroup->origin.v);
  59.     OffsetRect(&icon->iconBox,-kOffscreenOffset,0);
  60.     InvalRect(&icon->iconBox);
  61.     OffsetRect(&icon->textBox,-kOffscreenOffset,0);
  62.     InvalRect(&icon->textBox);
  63.     SetOrigin(0,0);
  64. }
  65.  
  66. #pragma segment Initialize
  67.  
  68. MSChildPtr NewMSChild(MSWindowPtr window,StringPtr title,
  69.         short x,short y,short h,short v,short grow,short minmax)
  70. {
  71.     short    i;
  72.     MSChildPtr    MSChild;
  73.     
  74.     MSChild = (MSChildPtr)NewPtrClear(sizeof(MSChildRecord));
  75.     MSChild->window = window;
  76.     MSChild->next = window->child;
  77.     window->child = MSChild;
  78.     for (i = 0; i <= title[0]; i++)
  79.         MSChild->title[i] = title[i];
  80.     MSChild->origin.h = x;
  81.     MSChild->origin.v = y;
  82.     SetRect(&MSChild->portRect, 0, 0, h * kIconStepH + 2 * kGrowBorder,
  83.                 v * kIconStepV + kPictHeight + kIconHdr + 2 * kGrowBorder);
  84.     MSChild->growBorder = grow;
  85.     MSChild->minmax = minmax;
  86.     SizeMSWindow(MSChild);
  87.     return(MSChild);
  88. }
  89.  
  90. MSWindowPtr NewMSWindow(StringPtr title,short x,short y,short h,short v,short grow)
  91. // if x and y are 0,0, then find the max device and center on it
  92. // otherwise, x and y are offsets from the topleft of gPMWindow
  93. {
  94. #pragma unused (grow)
  95.     WindowPtr    window;
  96.     Point        p;
  97.     
  98.     window = GetNewCWindow(rWindow, NewPtrClear(sizeof(MSWindowRecord)), (WindowPtr) -1);
  99.     SizeWindow(window, h * kIconStepH + 2 * kGrowBorder,
  100.                 v * kIconStepV + kPictHeight + kIconHdr + 2 * kGrowBorder,true);    // fUpdate
  101.     
  102.     if (x==0 && y==0) {    // for gPMWindow
  103.         GDHandle    dev;
  104.         
  105.         dev = GetMaxDevice( &(**GetGrayRgn()).rgnBBox );
  106.         p = CenterWithin( &window->portRect, &(**dev).gdRect );
  107.         }
  108.     else
  109.         {
  110.         WindowPtr     saved;
  111.         p.h = x; p.v = y;
  112.         GetPort(&saved);
  113.         SetPort((GrafPtr)gPMWindow);    // will have been made by now
  114.         LocalToGlobal(&p);
  115.         SetPort(saved);
  116.         }
  117.     MoveWindow(window,p.h,p.v,true);    // front
  118.     SetWTitle(window,title);
  119.                 
  120.     return((MSWindowPtr)window);
  121. }
  122.  
  123. void NewMSMenu(MSChildPtr MSChild,short id)
  124. {
  125.     MSMenuPtr    menu,lastmenu;
  126.     short        i,sz;
  127.     StringPtr    text;
  128.     
  129.     MSChild->menuBarRect.bottom = MSChild->menuBarRect.top + kMenuHeight;
  130.     menu = (MSMenuPtr)NewPtrClear(sizeof(MSMenuRecord));
  131.  
  132.     lastmenu = (MSMenuPtr)(&MSChild->menu);
  133.     while (lastmenu->next != nil)
  134.         lastmenu = lastmenu->next;
  135.     lastmenu->next = menu;
  136.  
  137.     menu->menu = GetMenu(id);
  138.     InsertMenu(menu->menu,-1);     /* install popup menu */
  139.     text = (*(menu->menu))->menuData;
  140.     sz = text[0];
  141.     if (sz > 31) sz = 31;
  142.     menu->text[0] = sz;
  143.     for (i = 1; i <= sz; i++)
  144.         menu->text[i] = text[i];
  145. }
  146.  
  147. void SetMSMenu(MSChildPtr MSChild)
  148. {
  149.     Rect        box;
  150.     MSMenuPtr    menu;
  151.     
  152.     box = MSChild->menuBarRect;
  153.     box.right = 10;
  154.     menu = MSChild->menu;
  155.     while (menu) {
  156.         box.left = box.right;
  157.         box.right += 2*10 + StringWidth((StringPtr)(menu->text));
  158.         menu->box = box;
  159.         menu = menu->next;
  160.     }
  161. }
  162.  
  163. MSIconPtr NewMSIcon(MSChildPtr MSChild,short id,short x,short y,short action)
  164. {
  165.     MSIconPtr icon;
  166.     
  167.     icon = (MSIconPtr)NewPtrClear(sizeof(MSIconRecord));
  168.     icon->next = MSChild->iconList;
  169.     MSChild->iconList = icon;
  170.     icon->id = id;
  171.     if (x < 0)
  172.         x = -x;
  173.     else
  174.         x = x * kIconStepH + kIconXOffset;
  175.     if (y < 0)
  176.         y = -y;
  177.     else
  178.         y = y * kIconStepV + kPictHeight + kIconHdr;
  179.     SetRect(&icon->iconBox,x,y,x+32,y+32);
  180.     icon->group = MSChild;
  181.     icon->action = action;
  182.     return(icon);
  183. }
  184.  
  185. Boolean InitializeApp(void)
  186. {
  187.     MSChildPtr    PMChild,MSChild;
  188.     MSIconPtr    gameIcon;
  189.     short        i,inx,id;
  190.     Handle        pict;
  191.     ResType        type;
  192.     Str255        text;
  193.     
  194.     /*
  195.     **    Test the computer to be sure we can do color.  
  196.     */
  197.     if (gMac.hasColorQD == false) {
  198.         SysBeep (50);
  199.         ExitToShell();                /* If no color QD, we must leave. */
  200.     }
  201.  
  202.     gUpRgn = NewRgn();            // some cursor regions
  203.     gRightRgn = NewRgn();
  204.     gURightRgn = NewRgn();
  205.     gDRightRgn = NewRgn();
  206.     gArrowRgn = NewRgn();
  207.  
  208.     gcUpRgn = NewRgn();            // more child cursor regions
  209.     gcRightRgn = NewRgn();
  210.     gcURightRgn = NewRgn();
  211.     gcDRightRgn = NewRgn();
  212.     gcArrowRgn = NewRgn();
  213.  
  214.     gClipRgn = NewRgn();        // some clipping regions
  215.     gViewRgn = NewRgn();
  216.     gDrawRgn = NewRgn();
  217.     gFrameRgn = NewRgn();
  218.     gParentFrameRgn = NewRgn();
  219.  
  220.     inx = 1;
  221.     while (pict = Get1IndResource('PICT',inx++)) {    // Preload the PICTs
  222.         GetResInfo(pict,&id,&type,text);
  223.         if (id < kMaxPict) {
  224.             gPicts[id] = (PicHandle)pict;
  225.             for (i = text[0] + 1; i >= 0; i--)
  226.                 gPictText[id][i] = text[i];        
  227.             DetachResource(pict);
  228.             MoveHHi(pict);
  229.             HLock(pict);        // Who need memory management ???
  230.         }
  231.     }
  232.  
  233.     /*    Create the windows    */
  234.     
  235.     gPMWindow = NewMSWindow("\pProgram Manager",0,0,6,6,kGrowBorder);
  236.  
  237.     PMChild = NewMSChild(gPMWindow,"\pProgram Manager",0,0,6,6,kGrowBorder,kMinMax);
  238.  
  239.     NewMSMenu(PMChild,mWinFile);
  240.     NewMSMenu(PMChild,mOptions);
  241.     NewMSMenu(PMChild,mWindow);
  242.     NewMSMenu(PMChild,mHelp);
  243.     SetMSMenu(PMChild);
  244.     PMChild->icon = NewMSIcon(PMChild,kProgramManager,0,0,0);    // mini window ??
  245.     HideIcon(PMChild->icon);
  246.  
  247.     MSChild = NewMSChild(gPMWindow,"\pMain",20,60,3,2,kGrowBorder,kMinMax);
  248.     gChild[iMain] = MSChild;
  249.     MSChild->icon = NewMSIcon(PMChild,kMain,0,5,0);
  250.     HideIcon(MSChild->icon);
  251.     NewMSIcon(MSChild,kFileManager,0,0,kBadPath);
  252.     NewMSIcon(MSChild,kDosPrompt,1,0,kUAEError);
  253.     MSChild->iconList->selected = true;    // kDosPrompt
  254.     NewMSIcon(MSChild,kControlPanel,2,0,kDrWatson);
  255.     NewMSIcon(MSChild,kClipboard,0,1,kNot3Error);
  256.     NewMSIcon(MSChild,kPrintManager,1,1,kLostPath);
  257.  
  258.     MSChild = NewMSChild(gPMWindow,"\pAccessories",360,60,2,3,kGrowBorder,kMinMax);
  259.     gChild[iAccessories] = MSChild;
  260.     MSChild->icon = NewMSIcon(PMChild,kAccessories,1,5,0);
  261.     HideIcon(MSChild->icon);
  262.     NewMSIcon(MSChild,kNotepad,0,0,kBadDir);
  263.     NewMSIcon(MSChild,kCalendar,1,0,kAssocError);
  264.     MSChild->iconList->selected = true;    // kCalendar
  265.     NewMSIcon(MSChild,kPaintbrush,0,1,kNoMem);
  266.     NewMSIcon(MSChild,kCalculator,1,1,kUAEError);
  267.     NewMSIcon(MSChild,kCardfile,0,2,kNot3Error);
  268.     NewMSIcon(MSChild,kClock,1,2,kAppClockErr);
  269.  
  270.     MSChild = NewMSChild(gPMWindow,"\pApplications",70,230,2,1,kGrowBorder,kMinMax);
  271.     gChild[iApplications] = MSChild;
  272.     MSChild->icon = NewMSIcon(PMChild,kApplications,3,5,0);
  273.     HideIcon(MSChild->icon);
  274.     NewMSIcon(MSChild,kTerminal,0,0,kNoComm);
  275.     MSChild->iconList->selected = true;    // kTerminal
  276.  
  277.     MSChild = NewMSChild(gPMWindow,"\pGames",200,190,2,2,kGrowBorder,kMinMax);
  278.     gChild[iGames] = MSChild;
  279.     MSChild->icon = NewMSIcon(PMChild,kGames,2,5,0);
  280.     HideIcon(MSChild->icon);
  281.     PMChild->iconList->selected = true;    // game
  282.     NewMSIcon(MSChild,kMinesweeper,0,0,0);
  283.     gameIcon = MSChild->iconList;
  284.     MSChild->iconList->selected = true;    // kMinesweeper
  285.     NewMSIcon(MSChild,kSolitare,1,0,kAssocError);
  286.     NewMSIcon(MSChild,kReversi,0,1,kNoMem);
  287.  
  288.     gMineWindow = NewMSWindow("p\WinMines",160,20,0,0,0);
  289.     MSChild = NewMSChild(gMineWindow,"\pWinMines",0,0,0,0,0,kMinMax);
  290.     NewMSMenu(MSChild,mMines);
  291.     NewMSMenu(MSChild,mMineHelp);
  292.     SetMSMenu(MSChild);
  293.     MSChild->icon = NewMSIcon(PMChild,kMinesweeper,4,5,0);
  294.     HideIcon(MSChild->icon);
  295.     MSChild->icon->app = gMineWindow;
  296.     gameIcon->app = gMineWindow;
  297.     
  298.     gAlertWindow = NewMSWindow("\pInvalid Path",180,120,4,2,0);
  299.     MSChild = NewMSChild(gAlertWindow,"\pInvalid Path",0,0,4,2,0,kNoMinMax);
  300.     NewMSIcon(MSChild,kCautionIcon,-(kIconHdr+kGrowBorder),-50,0);
  301.     NewMSIcon(MSChild,kErrorIcon,-(kIconHdr+kGrowBorder),-50,0);
  302.     NewMSIcon(MSChild,kInfoIcon,-(kIconHdr+kGrowBorder),-50,0);
  303.     
  304.     gBlack.red    = gBlack.green    = gBlack.blue    = vBLACK;
  305.     gWhite.red    = gWhite.green    = gWhite.blue    = vWHITE;
  306.     gLtGray.red = gLtGray.green    = gLtGray.blue    = vLTGRAY;
  307.     gGray.red    = gGray.green    = gGray.blue    = vGRAY;
  308.     gDkGray.red = gDkGray.green    = gDkGray.blue    = vDKGRAY;
  309.     gBlue.red    = vDKGRAY; gBlue.green = vGRAY; gBlue.blue = vWHITE;
  310.  
  311.     GetDateTime(&gStartTime);
  312.     qd.randSeed = gStartTime;
  313.  
  314.     gGameType = iIntermediate - iBeginner;
  315.     NewGame(false);
  316.  
  317.     ShowWindow((WindowPtr)gPMWindow);
  318.     return(true);
  319. }
  320.  
  321. #pragma segment TheApp
  322.  
  323. void SizeMSWindow(MSChildPtr MSChild)
  324. {
  325.     Rect        box;
  326.  
  327.     box = MSChild->portRect;
  328.     box.bottom = kPictHeight;
  329.     box.left = box.right - kPictWidth;
  330.     MSChild->maximizeBox = box;
  331.     box.right = box.left;
  332.     box.left = box.right - kPictWidth2;
  333.     MSChild->minimizeBox = box;
  334.     box.right = kPictWidth;
  335.     box.left = 0;
  336.     MSChild->controlMenuBox = box;
  337.     box.right = 0;
  338.     MSChild->controlMenuRect = box;
  339.     box = MSChild->portRect;
  340.     box.top = kPictHeight;
  341.     box.bottom = box.top + ((MSChild->menu != nil) ? kMenuHeight : 0);    // a menu ??
  342.     InsetRect(&box,MSChild->growBorder,0);
  343.     MSChild->menuBarRect = box;
  344.     SetCursorRgns();
  345. }
  346.  
  347. void
  348. DrawIconText(MSIconPtr icon,short active)
  349. {
  350.     EraseRect(&icon->textBox);
  351.     if (active && icon->selected) {
  352.         RGBForeColor(&gBlue);    // the text hilite color
  353.         PaintRect(&icon->textBox);
  354.         RGBForeColor(&gBlack);
  355.     }
  356.     MoveTo(icon->textBox.left + 6,icon->textBox.bottom - 4);
  357.     DrawString(gPictText[icon->id]);
  358. }
  359.  
  360. void
  361. DrawPictBox(short id,Rect *box)
  362. {
  363.     PicHandle pict;
  364.     
  365.     if (pict = gPicts[id])
  366.         DrawPicture(pict,box);
  367. }
  368.  
  369. void
  370. DrawIcon(MSIconPtr icon,short active)
  371. {
  372.     PicHandle        pict;
  373.     short        w;
  374.     Rect         box;
  375.     
  376.     if (pict = gPicts[icon->id]) {
  377.         box = icon->iconBox;
  378.         DrawPicture(pict,&box);
  379.         if (w = StringWidth(gPictText[icon->id])) {
  380.             box.left += (kIconSize - w) / 2;
  381.             box.right = box.left + w;
  382.             box.bottom = icon->iconBox.bottom + kIconLineHeight;
  383.             InsetRect(&box,-6,-4);
  384.             box.top = icon->iconBox.bottom;
  385.             icon->textBox = box;
  386.             DrawIconText(icon,active);
  387.         }
  388.     }
  389. }
  390.  
  391. Boolean TrackTextBox(Rect *box)
  392. {
  393.     Point    where;
  394.     
  395. reclick:
  396.     while (StillDown()) {
  397.         GetMouse(&where);
  398.         if (PtInRect(where,box)) {
  399.             InvertRect(box);
  400.             while (StillDown()) {
  401.                 GetMouse(&where);
  402.                 if (!PtInRect(where,box)) {    // dragged out of the box
  403.                     InvertRect(box);
  404.                     goto reclick;                    // try again
  405.                 }
  406.             }
  407.             InvertRect(box);
  408.             return(true);
  409.         }
  410.     }
  411.     return(false);
  412. }
  413.  
  414. Boolean TrackButton(short id,Rect *box)
  415. {
  416.     Point    where;
  417.     
  418. reclick:
  419.     while (StillDown()) {
  420.         GetMouse(&where);
  421.         if (PtInRect(where,box)) {
  422.             DrawCell(id+kPressOffset,box);
  423.             while (StillDown()) {
  424.                 GetMouse(&where);
  425.                 if (!PtInRect(where,box)) {    // dragged out of the box
  426.                     DrawCell(id,box);
  427.                     goto reclick;                    // try again
  428.                 }
  429.             }
  430.             DrawCell(id,box);
  431.             return(true);
  432.         }
  433.     }
  434.     return(false);
  435. }
  436.  
  437. void ClickIcon(MSChildPtr MSChild,Point where,long modifiers)
  438. {
  439. #pragma unused (modifiers)
  440.     MSIconPtr    icon,lasticon;
  441.     
  442.     icon = MSChild->iconList;
  443.     while (icon) {
  444.         if (PtInRect(where,&icon->iconBox) ||
  445.             PtInRect(where,&icon->textBox)) {
  446.             lasticon = MSChild->iconList;
  447.             while (lasticon) {
  448.                 if (lasticon->selected) {    // bug, we don't drag multi clicks
  449.                     if (icon == lasticon) {
  450.                         if (gClicks == 2)
  451.                             DoubleClickIcon(MSChild,icon);
  452.                         return;
  453.                     }
  454.                     DrawIconText(lasticon,lasticon->selected = false);
  455.                     goto select;    // clear selection drawn below
  456.                 }
  457.                 lasticon = lasticon->next;
  458.             }
  459.             break;    // a hit
  460.         }
  461.         icon = icon->next;
  462.     }
  463.     return;        // no hit
  464.     
  465. reclick:
  466.     while (StillDown()) {
  467.         GetMouse(&where);
  468.         if (PtInRect(where,&icon->iconBox) ||
  469.             PtInRect(where,&icon->textBox)) {
  470. select:
  471.             DrawIconText(icon,icon->selected = true);
  472.             while (StillDown()) {
  473.                 GetMouse(&where);
  474.                 if (!(PtInRect(where,&icon->iconBox) ||
  475.                       PtInRect(where,&icon->textBox))) {    // dragged out of the box
  476.                     DrawIconText(icon,icon->selected = false);
  477.                     goto reclick;                    // turn off and try again
  478.                 }
  479.             }
  480.             return;        // good hit
  481.         }
  482.     }
  483.     DrawIconText(lasticon,lasticon->selected = true);    // restore last one
  484. }
  485.  
  486. void DoMSCommand(MSChildPtr MSChild,short command)
  487. {
  488.     Rect        view;
  489.     WindowPtr    window;
  490.     MSChildPtr    MSNextChild,MSParent;
  491.  
  492.     window = (WindowPtr)MSChild->window;
  493.     SetPort(window);                /* the window must be the current port... */
  494.     SetOrigin(0,0);
  495.     switch (command) {
  496.     case vMinimize:
  497.             if (MSChild->next == nil) {
  498.                 HideWindow(window);    
  499.                 window = FrontWindow();
  500.                 SetPort(window);
  501.             } else {
  502.                 view = MSChild->portRect;
  503.                 OffsetRect(&view,MSChild->origin.h,MSChild->origin.v);
  504.                 EraseRect(&view);
  505.                 InvalRect(&view);
  506.                 MSChild->icon->restore = MSChild;
  507.                 MSChild->origin.h |= kOffscreenOffset;
  508.                 if (MSChild->active) {
  509.                     MSNextChild = MSChild->next;
  510.                     while (MSNextChild && (MSNextChild->origin.h & kOffscreenOffset))
  511.                         MSNextChild = MSNextChild->next;
  512.                     if (MSNextChild) {
  513.                         MSNextChild->active = true;
  514.                         view = MSNextChild->portRect;
  515.                         OffsetRect(&view,MSNextChild->origin.h,MSNextChild->origin.v);
  516.                         EraseRect(&view);
  517.                         InvalRect(&view);
  518.                     }
  519.                 }
  520.             }
  521.             ShowIcon(MSChild->icon);
  522.             SetCursorRgns();
  523.             break;
  524.     case vRestore:
  525.             if (!MSChild->maximized) {
  526.                 if (gSound) SysBeep(4);
  527.             } else
  528.             if (MSChild->iconList) {    // PM windows only !!
  529.                 EraseRect(&MSChild->portRect);
  530.                 InvalRect(&MSChild->portRect);
  531.                 MSChild->portRect = MSChild->restoreRect;
  532.                 MSChild->origin = MSChild->restoreOrigin;
  533.                 if (MSChild->next == nil)    // base child
  534.                     SizeWindow(window,MSChild->portRect.right,MSChild->portRect.bottom,true);
  535.                 SizeMSWindow(MSChild);
  536.                 MSChild->maximized = false;
  537.             }
  538.             break;
  539.     case vMaximize:
  540.             if (MSChild->maximized) { 
  541.                 if (gSound) SysBeep(4);
  542.             } else 
  543.             if (MSChild->iconList) {    // PM windows only !!
  544.                 MSChild->restoreRect = MSChild->portRect;
  545.                 MSChild->restoreOrigin = MSChild->origin;
  546.                 MSParent = MSChild->next;
  547.                 if (MSParent == nil) {    // base child
  548.                     MoveWindow(window,0,20,true);    // menusize
  549.                     SizeWindow(window,qd.screenBits.bounds.right,
  550.                         qd.screenBits.bounds.bottom - 20,true);
  551.                     MSChild->portRect = window->portRect;
  552.                 } else {
  553.                     while (MSParent->next != nil)
  554.                         MSParent = MSParent->next;
  555.                     MSChild->portRect = MSParent->portRect;
  556.                     MSChild->portRect.bottom -= MSParent->menuBarRect.bottom;
  557.                     MSChild->origin.h = 0;
  558.                     MSChild->origin.v = MSParent->menuBarRect.bottom;
  559.                 }
  560.                 EraseRect(&MSChild->portRect);
  561.                 InvalRect(&MSChild->portRect);
  562.                 SizeMSWindow(MSChild);
  563.                 MSChild->maximized = true;
  564.             }
  565.             break;
  566.     }
  567. }
  568.  
  569. void DoControlMenu(MSChildPtr MSChild,Point where)
  570. {
  571. #pragma unused (where)
  572.     Point        pt;
  573.     MenuHandle    menu;
  574.     
  575.     pt.h = MSChild->controlMenuBox.left;
  576.     pt.v = MSChild->controlMenuBox.bottom;
  577.     LocalToGlobal(&pt);
  578.     menu = gMenus[mControlInx];
  579.     if ( MSChild->window == gAlertWindow ) {
  580.         DisableItem(menu, iMinimize);        /* the alert doesn't minimize */
  581.         DisableItem(menu, iMaximize);
  582.     } else {
  583.         EnableItem(menu, iMinimize);
  584.         EnableItem(menu, iMaximize);
  585.     }
  586.  
  587.     DoMenuCommand(MSChild,menu,PopUpMenuSelect(menu,pt.v,pt.h,1) );
  588. }
  589.  
  590. void DoMenuBar(MSChildPtr MSChild,Point where)
  591. {
  592.     Point        pt;
  593.     MSMenuPtr    menu;
  594.     
  595.     pt = where;
  596.     while(StillDown()) {
  597.         menu = MSChild->menu;
  598.         while (menu) {
  599.             if (PtInRect(pt,&menu->box))    // ??
  600.                 break;
  601.             menu = menu->next;
  602.         }
  603.         if (menu) {
  604.             InvertRect(&menu->box);
  605.             pt.h = menu->box.left;
  606.             pt.v = menu->box.bottom;
  607.             LocalToGlobal(&pt);
  608.             DoMenuCommand(MSChild,menu->menu,PopUpMenuSelect(menu->menu,pt.v,pt.h,1) );
  609.             InvertRect(&menu->box);
  610.         }
  611.         GetMouse(&where);
  612.     }
  613. }
  614.  
  615. void SetOkBox(WindowPtr window,Rect *box)
  616. {
  617.     *box = window->portRect;
  618.     box->left = (box->right - kOKBoxW) / 2;
  619.     box->right = box->left + kOKBoxW;
  620.     box->bottom -= 10;
  621.     box->top = box->bottom - kOKBoxH;
  622. }
  623.  
  624. void DrawOkBox(WindowPtr window)
  625. {
  626.     Rect        box;
  627.     PicHandle    pict;
  628.  
  629.     SetOkBox(window,&box);
  630.     if (pict = gPicts[kOKButton])
  631.         DrawPicture(pict,&box);
  632. }
  633.  
  634. void DrawAlertWindow(WindowPtr window)
  635. {
  636.     short        i,c,x,y,count;
  637.     MSChildPtr    MSChild;
  638.     Str255        text;
  639.     StringPtr    ptext,p;
  640.  
  641.     DrawMSWindow(window);
  642.     MSChild = ((MSWindowPtr)window)->child;
  643.     GetIndString(text,rTextStr,MSChild->iconList->action);
  644.  
  645.     DrawOkBox(window);
  646.     
  647.     TextFace(bold);
  648.     x = 60; y = kIconStepV;
  649.     ptext = text;
  650.     count = (*ptext) & 0xFF;
  651.     text[count + 1] = 0;
  652.     for (i = 0; i < count; i += c + 1) {
  653.         p = ptext + 1;
  654.         c = 0;
  655.         while (((*p) & 0xFF) >= ' ') {
  656.             p++;
  657.             c++;
  658.         }
  659.         *ptext = c;
  660.         MoveTo(x,y);
  661.         DrawString(ptext);
  662.         y += 16;
  663.         ptext = p;
  664.     }
  665.     TextFace(normal);
  666. }
  667.  
  668. void DoMSAlert(short action)
  669. {
  670.     short        i;
  671.     WindowPtr    window;
  672.     MSChildPtr    MSChild;
  673.     Str255        text;
  674.  
  675.     MSChild = gAlertWindow->child;
  676.     MSChild->iconList->action = action;
  677.     text[0] = 0;
  678.     GetIndString(text,rTitleStr,action);
  679.     for (i = text[0] + 1; i >= 0; i--)
  680.         MSChild->title[i] = text[i];
  681.  
  682.     window = (WindowPtr)gAlertWindow;
  683.     ShowWindow(window);
  684.     SelectWindow(window);
  685.     InvalRect(&window->portRect);
  686.  
  687.     if (gSound) SysBeep(4);
  688. }
  689.  
  690. void DoubleClickIcon(MSChildPtr MSChild,MSIconPtr icon)
  691. {
  692.     Point        where;
  693.     WindowPtr    window;
  694.  
  695.     if (icon->app) {
  696.         if (MSChild->next == nil)    // the PM base group
  697.             HideIcon(icon);
  698.         window = (WindowPtr)icon->app;
  699.         ShowWindow(window);            // was hidden, restore
  700.         SelectWindow(window);
  701.         SetPort(window);
  702.     } else
  703.     if (icon->restore) {
  704.         if (icon->iconBox.right < kOffscreenOffset)    // for Window menu
  705.             HideIcon(icon);
  706.         MSChild = icon->restore;
  707.         window = (WindowPtr)MSChild->window;
  708.         SetPort(window);
  709.         SetOrigin(0,0);        // redundant ??
  710.         MSChild->origin.h &= ~kOffscreenOffset;
  711.         where = MSChild->origin;
  712.         LocalToGlobal(&where);
  713.         BringChildFront(window,where,true);
  714.     } else
  715.     if (icon->action)
  716.         DoMSAlert(icon->action);
  717. }
  718.  
  719.  
  720. /*    This is called when a mouse-down event occurs in the content of a window.
  721.     Other applications might want to call FindControl, TEClick, etc., to
  722.     further process the click. */
  723.  
  724. Boolean ContentClick(EventRecord *event,WindowPtr window)
  725. {
  726.     Point        pt;
  727.     Rect        box;
  728.     MSChildPtr    MSChild;
  729.  
  730.     CountClicks(event);        // count for double clicks
  731.     MSChild = ((MSWindowPtr)window)->child;
  732.     while (MSChild != nil) {
  733.         SetOrigin( -MSChild->origin.h, -MSChild->origin.v);
  734.         pt = event->where;
  735.         GlobalToLocal(&pt);
  736.         if (PtInRect(pt,&MSChild->portRect)) {
  737.             if ((MSChild->next != nil) && (MSChild->window->child != MSChild)) {
  738.                 BringChildFront(window,event->where,true);
  739.                 MSChild = ((MSWindowPtr)window)->child;
  740.                 SetOrigin( -MSChild->origin.h, -MSChild->origin.v);
  741.                 pt = event->where;
  742.                 GlobalToLocal(&pt);
  743.             }
  744.             if (PtInRect(pt,&MSChild->controlMenuRect))    // is the menu already up ?
  745.                 DoControlMenu(MSChild,pt);
  746.             else
  747.             if (PtInRect(pt,&MSChild->menuBarRect))    // is there a window menu bar ?
  748.                 DoMenuBar(MSChild,pt);
  749.             else
  750.             if (pt.v < kPictHeight) {
  751.                 if (PtInRect(pt,&MSChild->controlMenuBox)) {
  752.                     DrawCell(kMenuBox+kPressOffset,&MSChild->controlMenuBox);
  753.                     DoControlMenu(MSChild,pt);
  754.                     DrawCell(kMenuBox,&MSChild->controlMenuBox);
  755.                 } else
  756.                 if (PtInRect(pt,&MSChild->maximizeBox)) {
  757.                     if (TrackButton((MSChild->maximized) ? kRestoreBox : kMaximizeBox,&MSChild->maximizeBox))
  758.                         DoMSCommand(MSChild,(MSChild->maximized) ? vRestore : vMaximize);
  759.                 } else
  760.                 if (PtInRect(pt,&MSChild->minimizeBox)) {
  761.                     if (TrackButton(kMinimizeBox,&MSChild->minimizeBox))
  762.                         DoMSCommand(MSChild,vMinimize);
  763.                 } else {
  764. //                    SetOrigin( 0, 0);
  765.                     return(false);        // allow dragging
  766.                 }
  767.             } else
  768.             if (window == gMineWindow) {
  769.                 if (PtInGame(pt)) {
  770.                     SetPort(window);
  771.                     ClickGame(pt,event->modifiers);
  772.                 }
  773.             } else
  774.             if (window == gAlertWindow) {
  775.                 SetOkBox(window,&box);
  776.                 if (PtInRect(pt,&box)) {
  777.                     if (TrackButton(kOKButton,&box)) {
  778.                         if (gDone)
  779.                             Terminate();        // this is the end...
  780.                         else
  781.                             HideWindow(window);
  782.                     }
  783.                 }
  784.             } else
  785.                 ClickIcon(MSChild,pt,event->modifiers);
  786.             MSChild = nil;
  787.         } else
  788.             MSChild = MSChild->next;
  789.     }
  790.     SetOrigin( 0, 0);
  791.     return(true);
  792. } /*ContentClick*/
  793.  
  794.  
  795. void DrawMSWindow(WindowPtr    window)
  796. {
  797.     short        x,x1,y,vBorder;
  798.     Rect        r,box;
  799.     MSIconPtr    icon;
  800.     MSChildPtr    MSParent,MSChild;
  801.     MSMenuPtr    menu;
  802.     
  803.     MSParent = ((MSWindowPtr)window)->child;
  804.     while (MSParent->next != nil)
  805.         MSParent = MSParent->next;
  806.     MSChild = ((MSWindowPtr)window)->child;
  807.  
  808.     /* start with parent's client area */
  809.     r = MSParent->portRect;
  810.     RectRgn(gParentFrameRgn,&r);
  811.     InsetRect(&r,kGrowBorder,kGrowBorder);
  812.     r.top = MSParent->menuBarRect.bottom;
  813.     RectRgn(gClipRgn,&r);
  814.     DiffRgn(gParentFrameRgn,gClipRgn,gParentFrameRgn);    // find parent frame region
  815.  
  816.     while (MSChild != nil) {
  817.         if (!(MSChild->origin.h & kOffscreenOffset)) {    // on screen
  818.             SetOrigin( -MSChild->origin.h, -MSChild->origin.v);
  819.             OffsetRgn(gClipRgn, -MSChild->origin.h, -MSChild->origin.v);
  820.             RectRgn(gViewRgn,&MSChild->portRect);
  821.             SectRgn(gClipRgn,gViewRgn,gDrawRgn);        // find my clip
  822.             if (MSChild == MSParent) {
  823.                 SetClip(gParentFrameRgn);
  824.                 UnionRgn(gDrawRgn,gParentFrameRgn,gDrawRgn);
  825.             } else {
  826.                 r = MSChild->portRect;
  827.                 InsetRect(&r,kGrowBorder,kGrowBorder);
  828.                 r.top = MSChild->menuBarRect.bottom;
  829.                 RectRgn(gFrameRgn,&r);
  830.                 DiffRgn(gDrawRgn,gFrameRgn,gFrameRgn);    // find my client area
  831.                 DiffRgn(gClipRgn,gViewRgn,gClipRgn);    // subtract the drawn view
  832.                 OffsetRgn(gClipRgn, MSChild->origin.h, MSChild->origin.v);
  833.                 SetClip(gFrameRgn);
  834.             }
  835.  
  836.             icon = MSChild->iconList;
  837.             if (icon) {        // assume PM windows have at lease one icon, game has none
  838.                 box = MSChild->portRect;
  839.                 FrameRect(&box);
  840.                 InsetRect(&box,1,1);
  841.                 if (MSChild->active)
  842.                     RGBForeColor(&gGray);
  843.                 else
  844.                     RGBForeColor(&gWhite);
  845.                 PenSize(2,2);
  846.                 FrameRect(&box);
  847.                 RGBForeColor(&gBlack);
  848.                 PenNormal();
  849.                 InsetRect(&box,2,2);
  850.                 FrameRect(&box);
  851.             }
  852.             x = 0;
  853.             y = 0;
  854.             vBorder = (MSChild->active) ? 0 : kInactiveOffset;
  855.             DrawPict(kMenuBox + vBorder,&x,&y);
  856.             for ( ; x < MSChild->portRect.right; )
  857.                 DrawPict(kTop + vBorder,&x,&y);
  858.             x = MSChild->portRect.right - kPictWidth;
  859.             if (MSChild->minmax) {
  860.                 x -= kPictWidth2;
  861.                 DrawPict(kMinimizeBox + vBorder,&x,&y);
  862.                 DrawPict(((MSChild->maximized) ? kRestoreBox : kMaximizeBox) + vBorder,&x,&y);
  863.             } else {
  864.                 MSChild->minimizeBox.right = MSChild->minimizeBox.left;
  865.                 MSChild->maximizeBox.right = MSChild->maximizeBox.left;
  866.                 DrawPict(kNoBox + vBorder,&x,&y);
  867.             }
  868.             
  869.             SetClip(gDrawRgn);
  870.             x -= StringWidth(MSChild->title) + 2*kPictWidth2;
  871.             MoveTo(x / 2,kPictHeight - 6);    // -5 with 14pt
  872.             TextFont(applFont);
  873.             TextFace(bold);
  874.             if (MSChild->active) {
  875.                 RGBForeColor(&gWhite);
  876.                 DrawString(MSChild->title);
  877.                 RGBForeColor(&gBlack);
  878.             } else
  879.                 DrawString(MSChild->title);
  880.             TextFace(normal);
  881.         
  882.             if (icon) {        // assume PM windows have at lease one icon, game has none
  883.                 x1 = MSChild->portRect.right - kPictWidth;
  884.                 x = 0;
  885.                 y = MSChild->portRect.bottom - kPictHeight;
  886.                 DrawPict(kBottomLeft + vBorder,&x,&y);
  887.                 x = x1;
  888.                 DrawPict(kBottomRight + vBorder,&x,&y);
  889.                 
  890.                 while (icon) {
  891.                     DrawIcon(icon,MSChild->active && (MSChild->window->child == MSChild));
  892.                     icon = icon->next;
  893.                 }
  894.             }
  895.             if (MSChild->menuBarRect.bottom != MSChild->menuBarRect.top) {
  896.                 EraseRect(&MSChild->menuBarRect);
  897.                 TextFace(bold);
  898.                 menu = MSChild->menu;
  899.                 while (menu) {
  900.                     MoveTo(menu->box.left + 10,menu->box.bottom - 4);
  901.                     DrawString((StringPtr)menu->text);
  902.                     menu = menu->next;
  903.                 }
  904.                 TextFace(normal);
  905.                 MoveTo(MSChild->menuBarRect.left,MSChild->menuBarRect.bottom);
  906.                 LineTo(MSChild->menuBarRect.right,MSChild->menuBarRect.bottom);
  907.             }
  908.         }
  909.         MSChild = MSChild->next;
  910.     }
  911.     SetOrigin(0,0);
  912.     /* restore a big rectangular region */
  913.     SetRectRgn(gClipRgn, -8000, -8000, 8000, 8000);
  914.     SetClip(gClipRgn);
  915. }
  916.  
  917. Boolean DragChild(WindowPtr window,Point where)
  918. {
  919.     Point        pt;
  920.     long        xy;
  921.     Rect        childRect,limitRect,slopRect;
  922.     MSChildPtr    MSParent,MSChild;
  923.     RgnHandle    rgn;
  924.     
  925.     SetPort(window);
  926.     SetOrigin(0,0);    // redundant ??
  927.     pt = where;
  928.     GlobalToLocal(&pt);
  929.     MSChild = ((MSWindowPtr)window)->child;
  930.     while (MSChild->next != nil) {
  931.         childRect = MSChild->portRect;
  932.         OffsetRect(&childRect,MSChild->origin.h,MSChild->origin.v);
  933.         if (PtInRect(pt,&childRect)) {
  934.             rgn = NewRgn();
  935.             RectRgn(rgn,&childRect);
  936.             MSParent = MSChild->next;
  937.             while (MSParent->next != nil)
  938.                 MSParent = MSParent->next;
  939.             limitRect = MSParent->portRect;
  940.             InsetRect(&limitRect,kGrowBorder + 1,kGrowBorder + 1);    // + 1 is slop ??
  941.             limitRect.top = MSParent->menuBarRect.bottom + 1;        // + 1 is slop ??
  942.             slopRect = limitRect;
  943.             InsetRect(&slopRect,-50,-50);
  944.             xy = DragGrayRgn(rgn,pt,&limitRect,&slopRect,0,nil);
  945.             // hysteresis ??
  946.             if (xy != 0x80008000) {
  947.                 EraseRect(&childRect);
  948.                 InvalRect(&childRect);
  949.                 OffsetRect(&childRect, LoWrd(xy), HiWrd(xy));
  950.                 EraseRect(&childRect);
  951.                 InvalRect(&childRect);
  952.                 *(long*)&MSChild->origin += xy;
  953.             }
  954.             DisposeRgn(rgn);
  955.             return(true);
  956.         } 
  957.         MSChild = MSChild->next;
  958.     }
  959.     return(false);
  960. }
  961.  
  962. /* Draw the contents of the application window. We do some drawing in color, using
  963.    Classic QuickDraw's color capabilities. This will be black and white on old
  964.    machines, but color on color machines. At this point, the window’s visRgn
  965.    is set to allow drawing only where it needs to be done. */
  966.  
  967. void DrawWindow(WindowPtr window)
  968. {
  969.     if (window == gMineWindow)
  970.         DrawMineWindow(window);
  971.     else
  972.     if (window == gAlertWindow)
  973.         DrawAlertWindow(window);
  974.     else
  975.         DrawMSWindow(window);
  976. } /*DrawWindow*/
  977.  
  978.  
  979. /*
  980. **    Read menu descriptions from resource file into memory 
  981. **    and store handles in gMenus array.
  982. **    Insert into MenuBar and draw.
  983. */
  984. void
  985. SetUpMenus(void)
  986. {
  987.     gMenus[mAppleInx] = GetMenu(mApple);     /* read menus from resource file */
  988.     AddResMenu(gMenus[mAppleInx], 'DRVR');    /* add desk accessory names to Apple menu */
  989.     gMenus[mFileInx] = GetMenu(mFile);
  990.     gMenus[mEditInx] = GetMenu(mEdit);
  991.     gMenus[mControlInx] = GetMenu(mControl);
  992.  
  993.     InsertMenu(gMenus[mAppleInx], 0);         /* install menus in menu bar */
  994.     InsertMenu(gMenus[mFileInx], 0);
  995.     InsertMenu(gMenus[mEditInx], 0);
  996.     InsertMenu(gMenus[mControlInx], -1);     /* install popup menu */
  997.  
  998.     DrawMenuBar();                            /* and draw menu bar */
  999. }
  1000.  
  1001.  
  1002. /*    
  1003. **    Display a dialog box
  1004. */
  1005. void
  1006. ShowDialog(short dialogID)
  1007. {
  1008.     DialogPtr    theDialog;
  1009.     short        itemHit;
  1010.  
  1011.     SetCursor(*GetCursor(kArrowCursor));
  1012.     theDialog = GetNewDialog(dialogID, nil, (WindowPtr) -1);
  1013.     
  1014.     PositionWindow( (WindowPtr) theDialog); // •••ets
  1015.     
  1016.     ModalDialog(nil,&itemHit);
  1017.     DisposDialog(theDialog);
  1018. }
  1019.  
  1020.  
  1021. /*    This is called when an item is chosen from the menu bar (after calling
  1022.     MenuSelect or MenuKey). It performs the right operation for each command.
  1023.     It is good to have both the result of MenuSelect and MenuKey go to
  1024.     one routine like this to keep everything organized. */
  1025.  
  1026. void
  1027. DoMenuCommand(MSChildPtr MSChild,MenuHandle hMenu,long mResult)
  1028. {
  1029.     short    theItem,                    /* menu item number from mResult low-order word */
  1030.             theMenu;                    /* menu number from mResult high-order word */
  1031.     Str255    name;                        /* desk accessory name */
  1032.     int        temp;
  1033.     Boolean    dummy;
  1034.  
  1035.     theItem = LoWrd(mResult);            /* call Toolbox Utility routines to */
  1036.     theMenu = HiWrd(mResult);            /* set menu item number and menu */
  1037.  
  1038.     switch (theMenu) {                    /* switch on menu ID */
  1039.  
  1040.         case mApple:
  1041.             switch (theItem) {
  1042.             case iAbout:        /* bring up About Box */
  1043.                 ShowDialog(rAbout);
  1044.                 break;
  1045.             default:            /* all non-About items in this menu are DAs */
  1046.                 GetItem(hMenu, theItem, name);
  1047.                 temp = OpenDeskAcc(name);
  1048.                 SetPort((WindowPtr)gMineWindow);
  1049.             }
  1050.             break;
  1051.  
  1052.         case mFile:
  1053.             switch (theItem) {            /* switch on menu item */
  1054.             case iProgramMgr:
  1055.                 ShowWindow((WindowPtr)gPMWindow);
  1056.                 break;
  1057.             case iSound:
  1058.                 CheckItem(hMenu,theItem,gSound = !gSound);
  1059.                 break;
  1060.             case iQuit:
  1061.                 goto logout;
  1062.             }
  1063.             break;
  1064.  
  1065.         case mEdit:
  1066.             dummy = SystemEdit(theItem - 1); /* Pass the command on to the Desk Manager. */
  1067.             break;
  1068.  
  1069.         case mWinFile:
  1070.             switch (theItem) {            /* switch on menu item */
  1071.             case iLogout:
  1072.         logout:
  1073.                 DoMSAlert(kExitMsg);
  1074.                 gDone = true;
  1075. //                Terminate();    // when the OK button is pressed
  1076.                 break;
  1077.             }
  1078.             break;
  1079.  
  1080.         case mOptions:
  1081.             CheckItem(hMenu,theItem,gOptions[theItem] = !gOptions[theItem - 1]);
  1082.             break;
  1083.  
  1084.         case mWindow:
  1085.             switch (theItem) {
  1086.             case iCascade:
  1087.                 break;
  1088.             case iTile:
  1089.                 break;
  1090.             case iArrange:
  1091.                 break;
  1092.  
  1093.             case iMain:
  1094.             case iAccessories:
  1095.             case iApplications:
  1096.             case iGames:
  1097.                 MSChild = gChild[theItem];
  1098.                 MSChild->icon->restore = MSChild;
  1099.                 DoubleClickIcon(MSChild,MSChild->icon);
  1100.                 break;
  1101.             }
  1102.             break;
  1103.  
  1104.         case mControl:
  1105.             switch (theItem) {
  1106.             case iRestore:
  1107.                 DoMSCommand(MSChild,vRestore);
  1108.                 break;
  1109.             case iMove:
  1110.                 break;
  1111.             case iWinSize:
  1112.                 break;
  1113.             case iMinimize:
  1114.                 DoMSCommand(MSChild,vMinimize);
  1115.                 break;
  1116.             case iMaximize:
  1117.                 DoMSCommand(MSChild,(MSChild->maximized) ? vRestore : vMaximize);
  1118.                 break;
  1119.             case iWinClose:
  1120.                 HideWindow((WindowPtr)(MSChild->window));
  1121.                 break;
  1122.             case iSwitchTo:
  1123.                 break;
  1124.             }
  1125.             break;
  1126.  
  1127.         case mHelp:
  1128.             if (theItem == iAboutHelp)        /* bring up About Box */
  1129.                 ShowDialog(rAbout);
  1130.             else
  1131.                 DoMSAlert(kHelpMsg);
  1132.             break;
  1133.  
  1134.         case mMineHelp:
  1135.             if (theItem == iAboutMines)        /* bring up About Box */
  1136.                 ShowDialog(rAboutMines);
  1137.             else
  1138.                 DoMSAlert(kHelpMsg);
  1139.             break;
  1140.  
  1141.         case mMines:
  1142.             switch (theItem) {            /* switch on menu item */
  1143.             case iBeginner:
  1144.             case iIntermediate:
  1145.             case iExpert:
  1146.                 CheckItem(hMenu, gGameType + iBeginner, false);
  1147.                 gGameType = theItem - iBeginner;
  1148.                 CheckItem(hMenu, theItem, true);
  1149.                 NewGame(true);
  1150.                 break;
  1151.             case iNew:
  1152.                 NewGame(false);
  1153.                 break;
  1154.             case iCustom:
  1155.                 ShowDialog(rCustom);
  1156.                 break;
  1157.             case iMarks:
  1158.                 CheckItem(hMenu, iMarks, gMarks = !gMarks);
  1159.                 break;
  1160.             case iTimes:
  1161.                 ShowDialog(rBestTimes);
  1162.                 break;
  1163.             }
  1164.             break;
  1165.     }
  1166.  
  1167.     HiliteMenu(0);                        /* Unhighlight menu title */
  1168.                                         /* (highlighted by MenuSelect) */
  1169. }
  1170.  
  1171. void
  1172. CreateGWorld(Rect *bounds)
  1173. {
  1174.     /*************************************************************************/
  1175.     /* Allocate a new GWorld for the offscreen drawing and store its PixMap. */
  1176.     /*************************************************************************/
  1177.     
  1178.     if (gGWorld!= nil)
  1179.         DisposeGWorld( gGWorld );
  1180.     NewGWorld( &gGWorld, 8, bounds, nil, nil, 0 );
  1181. }
  1182.  
  1183. void
  1184. SaveBits(WindowPtr window)
  1185. {
  1186.     CGrafPtr        currentPort;
  1187.     GDHandle        currentDevice;
  1188.     PixMapHandle    pixMap;            /* PixMap of the GWorld */
  1189.     
  1190.     /******************************************************************************/
  1191.     /* Store the current port and device before switching to the offscreen world. */
  1192.     /******************************************************************************/
  1193.     
  1194.     GetGWorld( ¤tPort, ¤tDevice );
  1195.     
  1196.     /****************************************************************************/
  1197.     /* Switch to the offscreen GWorld then lock the offscreen buffer in memory. */
  1198.     /****************************************************************************/
  1199.  
  1200.     SetGWorld( gGWorld, nil );
  1201.     pixMap = gGWorld->portPixMap;    //    GetGWorldPixMap(gGWorld);
  1202.     LockPixels( pixMap );
  1203.     
  1204.     RGBForeColor(&gBlack);
  1205.     RGBBackColor(&gWhite);
  1206.     ClipRect(&window->portRect);
  1207.     CopyBits(&window->portBits, (BitMap *) *pixMap, 
  1208.             &window->portRect, &window->portRect, srcCopy, nil);
  1209.  
  1210.     /********************************************************************/
  1211.     /* After drawing the image, unlock the offscreen buffer in memory    */
  1212.     /*    and set the port and device back to the window's.                */
  1213.     /********************************************************************/
  1214.  
  1215.     UnlockPixels( pixMap );
  1216.     SetGWorld( currentPort, currentDevice );
  1217. }
  1218.  
  1219. void
  1220. DrawMineWindow(WindowPtr window)
  1221. {
  1222.     CGrafPtr    currentPort;
  1223.     GDHandle    currentDevice;
  1224.     PixMapHandle    pixMap;            /* PixMap of the GWorld */
  1225.     
  1226.     /******************************************************************************/
  1227.     /* Store the current port and device before switching to the offscreen world. */
  1228.     /******************************************************************************/
  1229.     
  1230.     GetGWorld( ¤tPort, ¤tDevice );
  1231.     pixMap = gGWorld->portPixMap;    //    GetGWorldPixMap(gGWorld);
  1232.     
  1233.     /****************************************************************************/
  1234.     /* Switch to the offscreen GWorld then lock the offscreen buffer in memory. */
  1235.     /****************************************************************************/
  1236.  
  1237.     SetGWorld( gGWorld, nil );
  1238.     LockPixels( pixMap );
  1239.     
  1240.     DrawMSWindow(window);
  1241.     DrawGame( (BitMap *)*pixMap );
  1242.     
  1243.     /********************************************************************/
  1244.     /* After drawing the image, unlock the offscreen buffer in memory    */
  1245.     /*    and set the port and device back to the window's.                */
  1246.     /********************************************************************/
  1247.  
  1248.     SetGWorld( currentPort, currentDevice );
  1249.  
  1250.     RGBForeColor(&gBlack);
  1251.     RGBBackColor(&gWhite);
  1252.     ClipRect(&window->portRect);
  1253.     CopyBits ((BitMap *) *pixMap, &window->portBits, 
  1254.             &window->portRect, &window->portRect, srcCopy, nil);
  1255.     UnlockPixels( pixMap );
  1256. }
  1257.  
  1258. #define topLeft(x) (*((Point *) &(x)))
  1259. #define botRight(x) (*((Point *) &(x)+1))
  1260.  
  1261. void    PositionWindow( WindowPtr w )    
  1262. {
  1263.     WindowPtr    saved;
  1264.     Rect        r;
  1265.     Point        p;
  1266.     
  1267.     r = ((GrafPtr)gPMWindow)->portRect;
  1268.     
  1269.     GetPort(&saved);
  1270.     SetPort((GrafPtr)gPMWindow);
  1271.     LocalToGlobal(&topLeft(r));
  1272.     LocalToGlobal(&botRight(r));
  1273.     SetPort(saved);
  1274.     
  1275.     p = CenterWithin( &w->portRect, &r );
  1276.     MoveWindow( w, p.h, p.v, false);
  1277. }
  1278.  
  1279. Point    CenterWithin( Rect *r, Rect *within )
  1280. // within is in global coordinates
  1281. // returns global coordinate of r's topleft point
  1282. {
  1283.     Point        p;
  1284.     
  1285.     p.h = within->left + ((within->right-within->left) - (r->right-r->left))/2;
  1286.     p.v = within->top + ((within->bottom-within->top) - (r->bottom-r->top))/2;
  1287.     
  1288.     return p;
  1289. }